import { getRoot, setRoot, makeInitialData } from '../store/useStorage';
import type { StorageModel, Bookmark, Group, Settings } from '../types/model';

const BACKUP_TYPE = 'local-gce-backup';
const LEGACY_WETAB_TYPE = 'local-wetab-backup';
const VERSION = '1.0.0';

export async function exportBackup(): Promise<Blob> {
  // 归一化当前 root，确保包含所有必要字段
  let root = (await getRoot()) ?? makeInitialData();
  root = normalizeStorage(root as StorageModel);
  // 若 dockIds 缺失或为空，尝试从镜像键恢复后再导出
  try {
    const st: any = (globalThis as any)?.chrome?.storage?.local;
    if (st) {
      await new Promise<void>((resolve) => {
        try{
          st.get(['gceDockIdsBackup'], (res: any) => {
            const backup = Array.isArray(res?.gceDockIdsBackup) ? res.gceDockIdsBackup as string[] : [];
            const cur = Array.isArray((root as any)?.settings?.dockIds) ? (root as any).settings.dockIds as string[] : [];
            if (backup.length && (!cur || cur.length === 0)) {
              (root as any).settings.dockIds = backup.slice();
            }
            resolve();
          });
        }catch{ resolve(); }
      });
    }
  } catch {}
  const data = {
    type: BACKUP_TYPE,
    version: VERSION,
    exportedAt: new Date().toISOString(),
    payload: root,
  };
  const str = JSON.stringify(data, null, 2);
  return new Blob([str], { type: 'application/json' });
}

export interface ImportOptions {
  mode: 'merge' | 'override'; // 默认 merge
}

// 合并策略：以 id 为主键，重复则覆盖更新（用户偏好）
export async function importBackup(json: string, opts: ImportOptions = { mode: 'merge' }): Promise<void> {
  let parsed: any;
  try {
    parsed = JSON.parse(json);
  } catch (e) {
    throw new Error('备份文件格式无效，不是有效的JSON文件');
  }
  
  let incoming: StorageModel | null = null;
  // 接受两种类型：本项目与 Wetab 的统一类型；版本放宽为任意字符串
  if (parsed?.type && (parsed.type === BACKUP_TYPE || parsed.type === LEGACY_WETAB_TYPE)) {
    if (!parsed.payload) {
      throw new Error('备份文件缺少数据内容（payload）');
    }
    incoming = parsed.payload as StorageModel;
  } else if (isGceLegacyBackup(parsed)) {
    // 兼容 GCE（原 Wetab）备份格式
    try {
      incoming = convertGceLegacyToStorage(parsed);
    } catch (e) {
      throw new Error('GCE 旧版备份文件解析失败：' + (e instanceof Error ? e.message : '未知错误'));
    }
  } else {
    // 宽松识别：如果结构上存在 payload 且包含核心字段，也尝试按新格式处理
    if (parsed && parsed.payload && (parsed.payload.settings || parsed.payload.engines || parsed.payload.bookmarks || parsed.payload.groups)) {
      incoming = parsed.payload as StorageModel;
    } else {
      throw new Error('不支持的备份文件类型或版本');
    }
  }
  
  // 归一化传入数据，避免字段为非数组/缺省导致后续迭代错误
  incoming = normalizeStorage(incoming);
  const cur = normalizeStorage((await getRoot()) ?? makeInitialData());
  
  if (opts.mode === 'override') {
    const curRoot = normalizeStorage((await getRoot()) ?? makeInitialData());
    const normalizedIncoming = normalizeStorage(incoming);
    // 若备份不包含 dockIds，则保留当前 dockIds，避免 Dock 丢失
    const incomingDock = Array.isArray((normalizedIncoming.settings as any)?.dockIds) ? (normalizedIncoming.settings as any).dockIds : [];
    const curDock = Array.isArray((curRoot.settings as any)?.dockIds) ? (curRoot.settings as any).dockIds : [];
    if ((!incomingDock || incomingDock.length === 0) && curDock.length) {
      (normalizedIncoming.settings as any).dockIds = curDock.slice();
    }
    // 兜底：仍为空则尝试从镜像键恢复
    if (!Array.isArray((normalizedIncoming.settings as any).dockIds) || (normalizedIncoming.settings as any).dockIds.length === 0) {
      try{
        const st: any = (globalThis as any)?.chrome?.storage?.local;
        if (st) {
          await new Promise<void>((resolve)=>{
            try{
              st.get(['gceDockIdsBackup'], (res: any) => {
                const backup = Array.isArray(res?.gceDockIdsBackup) ? res.gceDockIdsBackup as string[] : [];
                if (backup.length) { (normalizedIncoming.settings as any).dockIds = backup.slice(); }
                resolve();
              });
            }catch{ resolve(); }
          });
        }
      }catch{}
    }
    await setRoot(normalizedIncoming);
    return;
  }
  
  // merge 覆盖重复内容
  // 若备份中 dockIds 为空而当前存在非空 dockIds，倾向保留当前（避免意外清空）
  try{
    const incDock = Array.isArray((incoming.settings as any)?.dockIds) ? (incoming.settings as any).dockIds as string[] : [];
    const curDock = Array.isArray((cur.settings as any)?.dockIds) ? (cur.settings as any).dockIds as string[] : [];
    if (incDock.length === 0 && curDock.length > 0) {
      try { delete (incoming.settings as any).dockIds; } catch {}
    }
  }catch{}
  const merged: StorageModel = {
    settings: normalizeSettings({ ...(cur.settings ?? {}), ...(incoming.settings ?? {}) } as Settings),
    engines: mergeArrayById(cur.engines ?? [], incoming.engines ?? []),
    bookmarks: mergeArrayById(cur.bookmarks ?? [], incoming.bookmarks ?? []),
    groups: mergeArrayById(cur.groups ?? [], incoming.groups ?? []),
  } as StorageModel;
  
  // 兜底：合并后的 dockIds 若仍为空，尝试从镜像键恢复
  try{
    const d = (merged.settings as any)?.dockIds;
    if (!Array.isArray(d) || d.length === 0) {
      const st: any = (globalThis as any)?.chrome?.storage?.local;
      if (st) {
        await new Promise<void>((resolve)=>{
          try{
            st.get(['gceDockIdsBackup'], (res: any) => {
              const backup = Array.isArray(res?.gceDockIdsBackup) ? res.gceDockIdsBackup as string[] : [];
              if (backup.length) { (merged.settings as any).dockIds = backup.slice(); }
              resolve();
            });
          }catch{ resolve(); }
        });
      }
    }
  }catch{}
  await setRoot(normalizeStorage(merged));
}

function mergeArrayById<T extends { id: string }>(a: T[], b: T[]): T[] {
  const map = new Map<string, T>();
  for (const item of a) map.set(item.id, item);
  for (const item of b) map.set(item.id, { ...(map.get(item.id) ?? {} as T), ...item });
  return Array.from(map.values());
}

// -------- 旧版备份适配（GCE/Wetab） --------
function isGceLegacyBackup(obj: any): boolean {
  return !!(obj && obj.version && obj.data && obj.data['store-icon'] && Array.isArray(obj.data['store-icon'].icons));
}

function convertGceLegacyToStorage(legacy: any): StorageModel {
  if (!legacy || !legacy.data || !legacy.data['store-icon'] || !Array.isArray(legacy.data['store-icon'].icons)) {
    throw new Error('旧版备份数据结构不正确');
  }
  
  const icons = legacy.data['store-icon'].icons as any[];
  const groups: Group[] = [];
  const bookmarks: Bookmark[] = [];
  const now = Date.now();
  
  for (let gi = 0; gi < icons.length; gi++) {
    const g = icons[gi];
    if (!g || typeof g !== 'object') continue;
    
    const gid: string = g.id || `gp-${gi}`;
    groups.push({ 
      id: gid, 
      name: g.name || `分组${gi + 1}`, 
      order: (gi + 1) * 10, 
      icon: toGroupIcon(g.iconClass) 
    } as Group);
    
    const children = Array.isArray(g.children) ? g.children : [];
    for (let bi = 0; bi < children.length; bi++) {
      const c = children[bi];
      if (!c || c?.type !== 'site') continue;
      
      const url = c.target || '';
      if (!url || !url.startsWith('http')) continue; // 跳过无效URL
      
      const icon = c.bgType === 'image' ? c.bgImage : '';
      const color = c.bgType === 'color' ? (c.bgColor || '') : '';
      
      bookmarks.push({
        id: c.id || `bm-${gi}-${bi}`,
        title: c.name || '未命名',
        url,
        icon,
        color: color || undefined,
        groupId: gid,
        order: (bi + 1) * 10,
        createdAt: c.updateTime || now,
        updatedAt: c.lasttime || c.updateTime || now,
      } as Bookmark);
    }
  }
  
  return { 
    settings: makeInitialData().settings, 
    engines: makeInitialData().engines, 
    bookmarks, 
    groups 
  } as StorageModel;
}

function toGroupIcon(iconClass?: string): string | undefined {
  // 可拓展为映射到内置 SVG，这里先原样保存 class 供前端选择性渲染
  return iconClass || undefined;
}

// -------- 归一化工具 --------
function normalizeSettings(s?: Partial<Settings>): Settings {
  const base = makeInitialData().settings as any;
  const out: any = {
    version: s?.version ?? base.version,
    openMode: (s?.openMode === 'current' || s?.openMode === 'newtab') ? s.openMode : base.openMode,
    iconSize: (s?.iconSize === 'sm' || s?.iconSize === 'md' || s?.iconSize === 'lg') ? s.iconSize : base.iconSize,
    iconPx: typeof s?.iconPx === 'number' ? s.iconPx : base.iconPx,
    showName: typeof s?.showName === 'boolean' ? s.showName : base.showName,
    fabEnabled: typeof s?.fabEnabled === 'boolean' ? s.fabEnabled : base.fabEnabled,
    // 新增：保留浮动按钮定位配置
    fabPlacement: (s && s.fabPlacement && (s.fabPlacement as any).ax && (s.fabPlacement as any).ay !== undefined) ? s.fabPlacement : base.fabPlacement,
    defaultSearchId: s?.defaultSearchId ?? base.defaultSearchId,
    theme: (s?.theme === 'light' || s?.theme === 'dark') ? s.theme : base.theme,
    columns: typeof s?.columns === 'number' ? s.columns : base.columns,
    radius: typeof s?.radius === 'number' ? s.radius : base.radius,
    // 追加的设置字段，确保导入时不丢失
    cardOpacity: typeof s?.cardOpacity === 'number' ? s.cardOpacity : base.cardOpacity,
    contentMaxWidth: typeof s?.contentMaxWidth === 'number' ? s.contentMaxWidth : base.contentMaxWidth,
    backgroundDataUrl: typeof s?.backgroundDataUrl === 'string' ? s.backgroundDataUrl : base.backgroundDataUrl,
    backgroundOverlay: typeof s?.backgroundOverlay === 'number' ? s.backgroundOverlay : base.backgroundOverlay,
    backgroundBlur: typeof s?.backgroundBlur === 'number' ? s.backgroundBlur : base.backgroundBlur,
    backgroundPosition: (s?.backgroundPosition === 'center' || s?.backgroundPosition === 'top' || s?.backgroundPosition === 'bottom' || s?.backgroundPosition === 'left' || s?.backgroundPosition === 'right') ? s.backgroundPosition : base.backgroundPosition,
    backgroundSize: (s?.backgroundSize === 'cover' || s?.backgroundSize === 'contain' || s?.backgroundSize === 'auto' || s?.backgroundSize === 'tile') ? s.backgroundSize : base.backgroundSize,
    // 新增：Dock 快捷栏 ID 列表，导入时保留
    dockIds: Array.isArray((s as any)?.dockIds) ? (s as any).dockIds : (Array.isArray(base?.dockIds) ? base.dockIds : []),
  };
  // 兜底保留未知字段（向前兼容未来新增设置项）
  if (s && typeof s === 'object') {
    for (const k of Object.keys(s)) {
      if (!(k in out)) out[k] = (s as any)[k];
    }
  }
  return out as Settings;
}

function normalizeStorage(x: StorageModel): StorageModel {
  const mi = makeInitialData();
  const engines = Array.isArray(x.engines) ? x.engines : (Array.isArray((x as any).searchEngines) ? (x as any).searchEngines : mi.engines);
  const bookmarks = Array.isArray(x.bookmarks) ? x.bookmarks : [];
  const groups = Array.isArray(x.groups) ? x.groups : mi.groups;
  const settings = normalizeSettings(x.settings as any);
  return { settings, engines, bookmarks, groups } as StorageModel;
}
